import * as THREE from 'three'
import { Rubik } from './rubik'
import { TouchLine } from './touchLine'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
export class Main {
    private dom: HTMLElement
    public scene!: THREE.Scene
    public renderer!: THREE.WebGLRenderer
    private camera!: THREE.PerspectiveCamera
    private ambientLight!: THREE.AmbientLight
    private directionalLight!: THREE.DirectionalLight

    private width: number
    private height: number
    public originHeight!: number
    public originWidth!: number

    public frontViewName = 'frontRubik'
    public backViewName = 'backRubik'

    public frontRubik!: Rubik
    public backRubik!: Rubik

    public touchLine!: TouchLine

    public minPercent = 0.25

    private raycaster!: THREE.Raycaster

    private targetRubik!: Rubik

    private anotherRubik!: Rubik

    // 魔方转动相关
    private startPoint!: THREE.Vector3
    private endPoint!: THREE.Vector3
    private movePoint!: THREE.Vector3
    private isRotating = false
    private intersect!: THREE.Intersection
    private normalize!: THREE.Vector3
    private isTouching = false

    constructor(id: string) {
        this.dom = document.getElementById(id) as HTMLElement

        this.width = window.innerWidth
        this.height = window.innerHeight

        this.initScene()
        this.render()

        this.initEvent()
    }

    private createLight() {
        const ambientLight = new THREE.AmbientLight(0xffffff, 1)
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
        directionalLight.position.set(0, 200, 100)
        this.ambientLight = ambientLight
        this.directionalLight = directionalLight
    }

    private createCamera() {
        const camera = new THREE.PerspectiveCamera(45, this.width / this.height, 1, 10000)
        camera.position.set(0, 0, 400)
        camera.lookAt(0, 0, 0)
        this.camera = camera
        this.originHeight = Math.tan(this.camera.fov / 2 * Math.PI / 180) * this.camera.position.z * 2
        this.originWidth = this.originHeight * this.camera.aspect
    }

    private createScene() {
        this.createLight()
        this.createCamera()
        this.createRenderer()
    }

    private initObject() {
        // 滑动条
        this.touchLine = new TouchLine(this, 750, 64)

        // 添加正视图
        this.frontRubik = new Rubik(this)
        this.frontRubik.model(this.frontViewName)
        this.frontRubik.resizeHeight(0.5, 1)

        // 添加反视图
        this.backRubik = new Rubik(this)
        this.backRubik.model(this.backViewName)
        this.backRubik.resizeHeight(0.5, -1)
    }

    private createRenderer() {
        const renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: true
        })

        renderer.setClearColor(0x000000)

        renderer.setPixelRatio(window.devicePixelRatio)

        renderer.setSize(this.width, this.height)

        this.dom.appendChild(renderer.domElement)

        this.renderer = renderer
    }

    public initEvent() {
        this.renderer.domElement.addEventListener('mousedown', (e) => {
            e.preventDefault()
            if (this.touchLine.isHover(e)) {
                this.touchLine.enble()
                console.log('鼠标按下', e)
            } else {
                this.getIntersects(e)
                if (!this.isRotating && this.intersect) { // 触摸了并且没有转动
                    this.startPoint = this.intersect.point // 设置起始点
                }
            }
        })

        window.addEventListener('mousemove', (e) => {
            e.preventDefault()
            if (this.touchLine.isActive) {
                this.touchLine.move(e.clientY)
                let frontPercent = e.clientY / window.innerHeight
                let endPercernt = 1 - frontPercent
                this.frontRubik.resizeHeight(frontPercent, 1)
                this.backRubik.resizeHeight(endPercernt, -1)

                this.render()
            } else if (this.isTouching) {
                this.getIntersects(e)
                if (!this.isRotating && this.startPoint && this.intersect) {
                    this.movePoint = this.intersect.point
                    if (!this.movePoint.equals(this.startPoint)) {
                        // 转动
                    }
                }
            }
        })

        window.addEventListener('mouseup', (e) => {
            e.preventDefault()
            this.touchLine.disable()
            this.isTouching = false
        })
    }

    private getIntersects(event: MouseEvent) {
        // .offsetY、.offsetX以canvas画布左上角为坐标原点,单位px
        const px = event.offsetX;
        const py = event.offsetY;
        const x = (px / window.innerWidth) * 2 - 1;
        const y = -(py / window.innerHeight) * 2 + 1;
        //创建一个射线投射器`Raycaster`
        this.raycaster = new THREE.Raycaster();
        this.raycaster.setFromCamera(new THREE.Vector2(x, y), this.camera);

        let rubikTypeName;
        if (this.touchLine.screenRect.top > event.clientY) {
            this.targetRubik = this.frontRubik;
            this.anotherRubik = this.backRubik;
            rubikTypeName = this.frontViewName;
        } else if (this.touchLine.screenRect.top + this.touchLine.screenRect.height < event.clientY) {
            this.targetRubik = this.backRubik;
            this.anotherRubik = this.frontRubik;
            rubikTypeName = this.backViewName;
        }
        let targetIntersect;
        for (let i = 0; i < this.scene.children.length; i++) {
            if (this.scene.children[i].name == rubikTypeName) {
                targetIntersect = this.scene.children[i];
                break;
            }
        }

        if (targetIntersect) {
            let intersects = this.raycaster.intersectObjects(targetIntersect.children);
            if (intersects.length > 2) {
                this.isTouching = true;
                if (intersects[0].object.name == 'coverCube') {
                    this.intersect = intersects[1];
                    this.normalize = intersects[0].face!.normal;
                    console.log(intersects[0].object.name);
                } else {
                    this.intersect = intersects[0];
                    this.normalize = intersects[1].face!.normal;
                }
            }
        }
    }

    private rotateRubik() {
        const sub = this.movePoint.sub(this.startPoint); // 计算滑动方向
    }

    private initScene() {
        this.createScene()
        const scene = new THREE.Scene()
        scene.add(this.ambientLight)
        scene.add(this.directionalLight)
        this.scene = scene
        this.initObject()
    }

    public render() {

        // const orbitControls = new OrbitControls(this.camera, this.renderer.domElement)
        this.renderer.render(this.scene, this.camera)
        // orbitControls.addEventListener('change', () => {
        //     this.renderer.render(this.scene, this.camera)
        // })
    }
}
